package com.javatip.project.deep_learning.model.controller;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

import com.javatip.project.deep_learning.app01Dataset.domain.App01Dataset;
import com.javatip.project.system.user.domain.User;
import com.javatip.project.system.user.service.IUserService;
import io.swagger.annotations.Api;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.javatip.project.deep_learning.model.domain.Model;
import com.javatip.project.deep_learning.model.service.IModelService;
import com.javatip.framework.web.controller.BaseController;
import com.javatip.framework.web.page.TableDataInfo;
import com.javatip.framework.web.domain.AjaxResult;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

/**
 * 模型信息操作处理
 *
 * @author 袁伟
 * @date 2024-06-18
 */
@Api(tags="语义分割模型管理")
@Controller
@RequestMapping("/deep_learning/model")
public class ModelController extends BaseController {
    private String prefix = "deep_learning/model";

    @Autowired
    private IModelService modelService;

    @Autowired
    private IUserService userService;

    @RequiresPermissions("deep_learning:model:view")
    @GetMapping()
    public String model() {
        return prefix + "/model";
    }

    /**
     * 查询模型列表
     */
    @RequiresPermissions("deep_learning:model:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(Model model) {
//        startPage();
        List<Model> list = modelService.selectModelList(model);
//        添加用户名
        for (Model m : list) {
            String userName = userService.getUsernameByUserId(Long.valueOf(m.getUserId()));
            m.setUserName(userName);
        }
        return getDataTable(list);
    }

    /**
     * 新增模型
     */
    @GetMapping("/add")
    public String add() {
        return prefix + "/add";
    }

    /**
     * 新增保存模型
     */
    @RequiresPermissions("deep_learning:model:add")
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(Model model) {
        return toAjax(modelService.insertModel(model));
    }

    /**
     * 修改模型
     */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Integer id, ModelMap mmap) {
        Model model = modelService.selectModelById(id);
        mmap.put("model", model);
        return prefix + "/edit";
    }

    /**
     * 修改保存模型
     */
    @RequiresPermissions("deep_learning:model:edit")
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(Model model) {
        return toAjax(modelService.updateModel(model));
    }

    /**
     * 删除模型
     */
    @RequiresPermissions("deep_learning:model:remove")
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        return toAjax(modelService.deleteModelByIds(ids));
    }

    @RequiresPermissions("deep_learning:model:remove")
    @PostMapping("/removeWithDb")
    @ResponseBody
    public AjaxResult removeWithDbUrl(String ids, String location) {
        return (modelService.deleteModelByIdsandLocation(ids, location));
    }


    @PostMapping("/uploadModel")
    @ResponseBody
    public AjaxResult addModel(Model model, MultipartHttpServletRequest request) {
        System.out.println("uploadModel");
//前端传过来的参数

//		System.out.println(model);
        String fitHeight = request.getParameter("fitHeight");
        String fitWidth = request.getParameter("fitWidth");
        String inputChannel = request.getParameter("inputChannel");
        String outputChannel = request.getParameter("outputChannel");
        String modelName = request.getParameter("modelName");
        String isPublic = request.getParameter("isPublic");
        Long userId = getSysUser().getUserId();
        // 获取文件
        List<MultipartFile> files = request.getFiles("file");

        // 权重文件
        List<MultipartFile> weightFile = request.getFiles("weightFile");
//        System.out.println("files:" + files.size());


//        打印前端传过来的参数
//		System.out.println("model.getId():"+model.getId());
//		System.out.println("fitHeight:"+fitHeight);
//		System.out.println("fitWidth:"+fitWidth);
//		System.out.println("inputChannel:"+inputChannel);
//		System.out.println("outputChannel:"+outputChannel);
//		System.out.println("modelName:"+modelName);
//		System.out.println("isPublic:"+isPublic);
//		System.out.println("userId:"+userId);

        model.setUserId(userId.intValue());
        Date date = new Date();
        date.setTime(System.currentTimeMillis());
        model.setUploadTime(date);
        model.setFitHeight(Integer.parseInt(fitHeight));
        model.setFitWidth(Integer.parseInt(fitWidth));
        model.setInputChannel(Integer.parseInt(inputChannel));
        model.setOutputChannel(Integer.parseInt(outputChannel));
        model.setModelName(modelName);
        model.setIsPublic(Integer.parseInt(isPublic));
        model.setIsWeight(false);
        // 打印当前路径
        String currentDirectory = System.getProperty("user.dir").replace("\\","/");
//        System.out.println("Current Directory: " + currentDirectory);
        // 模型保存路径
//        modelName后加上当前时间,年月日时分秒，防止重名
//        String modelSavePath = currentDirectory + "/src/main/resources/model/" + model.getUserId() + "/" + modelName + "_" + date.toString() + "/";
//        String modelSavePath = currentDirectory + "/src/main/resources/model/" + model.getUserId() + "/" + modelName + "_" + model.getUploadTime().toString().replace(":","")+ "/";
        String modelSavePath = currentDirectory + "/src/main/resources/model/" + model.getUserId() + "/"  + modelName+ "/";


//        System.out.println("modelSavePath:" + modelSavePath);
        for (MultipartFile file : files) {
            String fileName = file.getOriginalFilename();
//            System.out.println("fileName:" + fileName);
            String filePath = modelSavePath + fileName;
//            System.out.println("filePath:" + filePath);
            try {
                // 创建文件夹后保存文件
                File fileDirectory = new File(modelSavePath);
                if (!fileDirectory.exists()) {
                    fileDirectory.mkdirs();
//                    System.out.println("创建文件夹成功");
                }
                // 保存文件
                if (!file.isEmpty()) {
                    file.transferTo(new File(modelSavePath + fileName));
//                    System.out.println("保存文件成功");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            model.setLocation(filePath);
        }

        // weightFile重命名为0.pth
        if (!weightFile.isEmpty()) {
            model.setIsWeight(true);
            MultipartFile weightFile0 = weightFile.get(0);
            String weightFilePath = modelSavePath + "1.pth";
            try {
                // 创建文件夹后保存文件
                File fileDirectory = new File(modelSavePath);
                if (!fileDirectory.exists()) {
                    fileDirectory.mkdirs();
//                    System.out.println("创建文件夹成功");
                }
                // 保存文件
                if (!weightFile0.isEmpty()) {
                    weightFile0.transferTo(new File(weightFilePath));
                    model.setIsWeight(true);
//                    System.out.println("保存权重文件成功");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        AjaxResult ajax = toAjax(modelService.insertModel(model));
        appendPythonMethod(model.getId(), modelName, model.getInputChannel(), model.getOutputChannel());
//        System.out.println("model:" + model);
        return ajax;
    }

    //    返回自己的或者公开的模型列表
    @PostMapping("/listWithParas")
    @ResponseBody
    public TableDataInfo listWithOnlyUserId(Model model) {
//        startPage();
        List<Model> list = modelService.selectModelList(model);
//        TableDataInfo dataTable = getDataTable(list);
//        筛选list中的数据，只返回当前用户和isPublic为1的数据集
        List<Model> list1 = new ArrayList<>();
        User currentUser = getSysUser();
        int currentUserId = Integer.parseInt(String.valueOf(currentUser.getUserId()));
//        System.out.println("当前用户id: " + currentUserId);
        for (Model tmpModel : list) {
//            System.out.println("dataset.getUserId() = " + dataset);
            if (tmpModel.getIsPublic() != null) {
                if (tmpModel.getUserId() == currentUserId
                        || tmpModel.getIsPublic() == 1
                ) {
                    list1.add(tmpModel);
                }
            }
        }
        //        添加用户名
        for (Model m : list1) {
            String userName = userService.getUsernameByUserId(Long.valueOf(m.getUserId()));
            m.setUserName(userName);
        }
//        System.out.println(list1);
        return getDataTable(list1);
//        return dataTable;
    }


    //    返回自己的模型列表
    @PostMapping("/listWithOnlyUserId")
    @ResponseBody
    public TableDataInfo listWithOnlyUserI(Model model) {
//        startPage();
        List<Model> list = modelService.selectModelList(model);
//        TableDataInfo dataTable = getDataTable(list);
//        筛选list中的数据，只返回当前用户和isPublic为1的数据集
        List<Model> list1 = new ArrayList<>();
        User currentUser = getSysUser();
        int currentUserId = Integer.parseInt(String.valueOf(currentUser.getUserId()));
//        System.out.println("当前用户id: " + currentUserId);
        for (Model tmpModel : list) {
//            System.out.println("dataset.getUserId() = " + dataset);
            if (tmpModel.getIsPublic() != null) {
                if (tmpModel.getUserId() == currentUserId
                ) {
                    list1.add(tmpModel);
                }
            }
        }
        //        添加用户名
        for (Model m : list1) {
            String userName = userService.getUsernameByUserId(Long.valueOf(m.getUserId()));
            m.setUserName(userName);
        }
//        System.out.println(list1);
        return getDataTable(list1);
//        return dataTable;
    }


    // 追加方法到 Network.py 文件
    private void appendPythonMethod(int modelId, String fileNameWithoutExtension, int inputChannel, int outputChannel) {
        // 指定 Network.py 文件的路径
//        String networkFilePath = "/home/jolly/develop/project/java/xx-system/src/main/resources/NetWork/Network.py";
        String currentDirectory = System.getProperty("user.dir");
//        System.out.println("Current Directory: " + currentDirectory);
        // 模型保存路径
        String modelSavePath = currentDirectory + "/src/main/resources/NetWork/Network.py";

        // 生成唯一类名
        String moduleName = "model_" + fileNameWithoutExtension + "_" + modelId;

        // 生成方法的代码
//        String methodCode = String.format(
//                "\ndef %s():\n" +
//                        "    module = imported_modules['%s']\n" +
//                        "    if hasattr(module, 'main'):\n" +
//                        "        return module.main()  # 调用 main 函数\n" +
//                        "    else:\n" +
//                        "        raise ImportError('Module does not have a main function')\n",
//                moduleName, moduleName
//        );
        String methodCode = String.format(
                "\ndef %s():\n" +
                        "    module = imported_modules['%s']\n" +
//                        "    if hasattr(module, 'main'):\n" +
                        "    return module.%s(%d,%d)  # 调用 main 函数\n"
//                        "    else:\n" +
//                        "        raise ImportError('Module does not have a main function')\n"
                ,
                moduleName,
                modelService.selectModelById(modelId).getUserId().toString() + '_'
                        + fileNameWithoutExtension + '_'
                        + modelService.selectModelById(modelId).getUploadTime().toString().replace(":","") + '_'
                        + fileNameWithoutExtension,
                fileNameWithoutExtension, inputChannel, outputChannel
        );

        // 追加方法代码到 Network.py
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(modelSavePath, true))) {
            writer.write(methodCode);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 检查模型名称是否存在
     *
     * @param name
     * @return
     */
    @GetMapping("/checkModelNameUnique")
    @ResponseBody
    public ResponseEntity<Boolean> checkModelNameUnique(@RequestParam("name") String name) {
        int userId = getSysUser().getUserId().intValue();
        boolean exists = modelService.isTrainModelNameExists(name, userId); // 该方法检查任务名称是否存在
        System.out.println("模型存在状态：" + exists);
        return ResponseEntity.ok(exists);
    }

    @GetMapping("/getIsWeight/{id}")
    @ResponseBody
    public Map<String, Boolean> getIsWeight(@PathVariable("id") Integer id) {
//        System.out.println("getIsWeight");
        Model model = modelService.selectModelById(id);
//        System.out.println("model.getIsWeight():"+model);
        Map<String, Boolean> response = new HashMap<>();
        response.put("isWeight", model.getIsWeight());
        return response;
    }
}
